#include <mockcpp/mockcpp.hpp>
#include <testngpp/testngpp.hpp>
#include <Square.h>

USING_MOCKCPP_NS
USING_TESTNGPP_NS

struct TestSquareData
{
    double width;
    double area;
    double perimeter;
    bool isValid;
};

TestSquareData validData[] =
{
        {2, 4, 8, true},
        {74.999, 5623.50, 299.96, true},
        {1.23, 1.51, 4.92, true},
        {1.22, 1.49, 4.88,true},
        {0.01, 0, 0.04, true}
};

TestSquareData invalidData[] =
{
        {-5, 0, 0, false},
        {0, 0, 0, false},
        {75, 0, 0, false}
};

FIXTURE(Square_getArea)
{


    SETUP()
    {
    }
    TEARDOWN()
    {
    }

    void test_getArea(const TestSquareData & validData)
    {
        const Square square(validData.width);
        ASSERT_EQ(validData.area, square.getArea());
    }

    TEST(Area of valid Square should be right)
    {
        for(int i=0; i< sizeof(validData)/sizeof(TestSquareData);i++)
        {
            test_getArea(validData[i]);
        }
    }

    TEST(Area of invalid Square should be 0)
    {
        for(int i=0; i< sizeof(invalidData)/sizeof(TestSquareData);i++)
        {
            test_getArea(invalidData[i]);
        }
    }

};

FIXTURE(Square_getPerimeter)
{
    SETUP()
    {
    }
    TEARDOWN()
    {
    }

    void test_getPerimeter(const TestSquareData & validData)
    {
        const Square square(validData.width);
        ASSERT_EQ( validData.perimeter, square.getPerimeter());
    }


    TEST(Perimeter of valid Square should be right)
    {
        for(int i=0; i< sizeof(validData)/sizeof(TestSquareData);i++)
        {
            test_getPerimeter(validData[i]);
        }
    }

    TEST(Perimeter of invalid Square should be 0)
    {
        for(int i=0; i< sizeof(invalidData)/sizeof(TestSquareData);i++)
        {
            test_getPerimeter(invalidData[i]);
        }
    }

};

FIXTURE(Square_isValid)
{


    SETUP()
    {
    }
    TEARDOWN()
    {
    }

     void test_isValid(const TestSquareData & validData)
    {
        const Square square(validData.width);
        ASSERT_EQ(validData.isValid, square.isValid());
    }

    TEST(isValid of valid Square should be true)
    {
        for(int i=0; i< sizeof(validData)/sizeof(TestSquareData);i++)
        {
            test_isValid(validData[i]);
        }
    }

    TEST(isValid of invalid Square should be false)
    {
        for(int i=0; i< sizeof(invalidData)/sizeof(TestSquareData);i++)
        {
            test_isValid(invalidData[i]);
        }
    }

};

FIXTURE(Square_changeWidth)
{
    void test_changeWidthSuccess(Square& square, const TestSquareData & data)
    {
       ASSERT_TRUE(square.changeWidth(data.width));
       ASSERT_EQ(data.area, square.getArea());
       ASSERT_EQ(data.perimeter, square.getPerimeter());
       ASSERT_TRUE(square.isValid());
    }

    TEST(isValid of valid Square should be true)
    {
        Square square(5);

        TestSquareData changeWidthData[] =
        {
                {3,  9, 12, true},
                {4,  16, 16, true},
                {5.008, 25,  20, true}
        };
        for(int i=0; i< sizeof(changeWidthData)/sizeof(TestSquareData);i++)
        {
            test_changeWidthSuccess(square, changeWidthData[i]);
        }
    }

    TEST(isValid of valid Square should be true)
    {
        Square square(5);

        double invalidWidth[] =
        {-1,0,75};


        for(int i=0; i< sizeof(invalidWidth)/sizeof(double);i++)
        {
            ASSERT_FALSE(square.changeWidth(invalidWidth[i]));
        }
    }
};
